import { ref, reactive, toRefs, onUnmounted } from 'vue';
import { hookResult, IS_MODAL } from './bindResult';

type BeforeShow<T> = (data: T) => any | Promise<any>;

export type ModalProps = {
  [key: string]: any;
  showFooter?: boolean;
  fullscreen?: boolean;
  title?: string;
};

export type FOnSuccess = (res: any) => void;

export function useModalBinder<T = any>(
  onShow: BeforeShow<T>,
  defaultProps: ModalProps = {}
) {
  const { showFooter, fullscreen, title } = defaultProps;

  const dialogVisible = ref<boolean>(false);

  // 设置modal其他参数
  const modalProps = reactive<Record<string, any>>({
    footer: showFooter ? true : null,
    wrapClassName: fullscreen ? 'full-modal' : '',
    loading: false,
    title,
  });

  async function showModal(data: T) {
    const res = await Promise.resolve(onShow(data));
    dialogVisible.value = true;
    return res;
  }

  function hideModal() {
    dialogVisible.value = false;
  }

  function setProps(props: any) {
    if (props) {
      Object.keys(props).forEach((key) => {
        modalProps[key] = props[key];
      });
    }
  }

  function triggerFooterVisible(b?: boolean) {
    if (b === undefined) {
      // null 不显示，undefined显示
      b = modalProps.footer === null;
    }
    modalProps.footer = b ? undefined : null;
  }

  function triggerLoading(b?: boolean) {
    if (b === undefined) {
      b = !modalProps.loading;
    }
    modalProps.loading = b;
  }

  // 不能正常切换，暂时隐藏
  // function triggerFullScreen(b?: boolean) {
  //   if (b === undefined) {
  //     b = !modalProps.wrapClassName;
  //   }
  //   modalProps.wrapClassName = b ? 'full-screen' : '';
  // }

  function setTitle(modalTitle: string) {
    modalProps.title = modalTitle;
  }

  function onClose() {
    hideModal();
  }

  const successCbSet = new Set<FOnSuccess>();

  const registerSuccess = (successCb: FOnSuccess) => {
    successCbSet.add(successCb);
  };
  const unregisterSuccess = (successCb: FOnSuccess) => {
    successCbSet.delete(successCb);
  };

  const triggerSuccess = (res: any) => {
    successCbSet.forEach((cb) => {
      cb(res);
    });
  };

  onUnmounted(() => {
    successCbSet.clear();
  });

  return hookResult(
    {
      showModal,
      hideModal,
      setProps,
      triggerFooterVisible,
      triggerLoading,
      triggerSuccess,
      setTitle,
      expose: {
        showModal,
        registerSuccess,
        unregisterSuccess,
        [IS_MODAL]: true,
      },
    },
    {
      visible: dialogVisible,
      onCancel: onClose,
      ...toRefs(modalProps),
    }
  );
}
